/**
  * PicDownloader 0.0.2a
  * PicDownloader is a small program for downloading images from imageboards.
  * This program was created using Qt 4.7.0
  * Version for desktop. See more on http://code.google.com/p/pic-downloader/
  *
  * Copyright (c) 2012, nd.anonymous.kun All rights reserved.
  *
  * Please contact with me by E-mail/XMPP: nd.anonymous.kun@gmail.com
  **/

#include "include/mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->label_url->installEventFilter(this);

    setVersions();
    initBoards();
    initPath();

    showMessage("Ready");
}


MainWindow::~MainWindow()
{
    delete ui;
}


bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type() == QEvent::MouseButtonPress)
    {
        if ( obj == ui->label_url )
        {
            QDesktopServices::openUrl(QUrl(HOME_PAGE));
        }
        return true;
    }
    else
    {
         // standard event processing
         return QObject::eventFilter(obj, event);
    }
}


void MainWindow::setVersions()
{
    ui->label_version->setText(PROGRAM_VERSION);
    ui->label_qt_version->setText(QT_USED_VERSION);
}


void MainWindow::initBoards()
{
    board = NOT_BOARD;
    boardsAddress.push_back(QString(DVACH_SO));
    boardsAddress.push_back(QString(NULLCHAN_RU));
    boardsAddress.push_back(QString(FORCHAN_ORG));
}


void MainWindow::initPath()
{
    path = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
    path += "\\PicDownloader";
    ui->lineEdit_path->setText(path);
}


void MainWindow::showMessage( const char* str )
{
    ui->statusBar->showMessage(QString(str));
}


void MainWindow::on_launchButton_clicked()
{
    startDownloading();
}


void MainWindow::on_pathSelectButton_clicked()
{
    path = QFileDialog::getExistingDirectory(this,"Select path to save");
    ui->lineEdit_path->setText(path);
}


void MainWindow::on_checkBox_minFSize_stateChanged(int v)
{
    ui->spinBox_minFSize->setEnabled(v);
}


void MainWindow::on_checkBox_maxFSize_stateChanged(int v)
{
    ui->spinBox_maxFSize->setEnabled(v);
}


void MainWindow::on_toolButton_test_clicked()
{
    testURL();
}


void MainWindow::on_checkBox_minImSize_stateChanged(int v)
{
    ui->spinBox_minImSizeW->setEnabled(v);
    ui->spinBox_minImSizeH->setEnabled(v);
}


void MainWindow::on_checkBox_maxImSize_stateChanged(int v)
{
    ui->spinBox_maxImSizeW->setEnabled(v);
    ui->spinBox_maxImSizeH->setEnabled(v);
}


void MainWindow::on_lineEdit_thread_returnPressed()
{
    ui->launchButton->click();
}


void MainWindow::on_lineEdit_thread_textChanged(QString )
{
    showMessage("Ready");
}


bool MainWindow::testURL()
{
    board = NOT_BOARD;
    url.setUrl(ui->lineEdit_thread->text());

    if (!url.isValid())
    {
        showMessage("Invalid URL");
        return false;
    }
    if ( url.scheme() != "http" )
    {
        showMessage("URL must start with 'http'");
        return false;
    }
    if ( url.path().isEmpty() )
    {
        showMessage("URL has no path");
        return false;
    }
    for ( int count=0; count<boardsAddress.size(); ++count )
    {
        if ( (url.host().indexOf(boardsAddress[count]) != -1) || (boardsAddress[count].indexOf(url.host()) != -1) )
        {
            url.setHost(boardsAddress[count]);
            board = count+1;    // Because first IB is #1, not #0: NULLCHAN_RU is #2, not #1
            break;
        }
    }
    if ( board == NOT_BOARD )
    {
        showMessage( QString("Host name "+url.host()+" is not defined").toAscii() );
        return false;
    }
    return true;
}


bool MainWindow::readParametrs()
{
    if ( ui->checkBox_minFSize->checkState() == Qt::Checked )
    {
        minFSize = ui->spinBox_minFSize->value();
    }
    if ( ui->checkBox_maxFSize->checkState() == Qt::Checked )
    {
        maxFSize = ui->spinBox_maxFSize->value();
    }
    if ( ui->checkBox_minImSize->checkState() == Qt::Checked )
    {
        minImSizeW = ui->spinBox_minImSizeW->value();
        minImSizeH = ui->spinBox_minImSizeH->value();
    }
    if ( ui->checkBox_maxImSize->checkState() == Qt::Checked )
    {
        maxImSizeW = ui->spinBox_maxImSizeW->value();
        maxImSizeH = ui->spinBox_maxImSizeH->value();
    }
    path = ui->lineEdit_path->text();
    return true;
}


bool MainWindow::createDirectory()
{
    path += "\\";
    QDir dir(path);
    if ( !dir.exists(path) )
        if ( !dir.mkdir(path) )
        {
            showMessage( QString("Cannot create directory: "+path).toAscii() );
            return false;
        }
    path += QFileInfo(url.path()).fileName();
    if ( !dir.exists(path) )
        if ( !dir.mkdir(path) )
        {
            showMessage( QString("Cannot create directory: "+path).toAscii() );
            return false;
        }
    return true;
}


bool MainWindow::startDownloading()
{
    ui->progressBar->setValue(0);

    if ( !readParametrs() )
        return false;
    if ( !testURL() )
        return false;

    ui->lineEdit_thread->setReadOnly(1);
    showMessage("Downloading thread...");

    QNetworkAccessManager* manager = new QNetworkAccessManager(this);
    manager->get(QNetworkRequest(url));
    connect ( manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(QnamFinished(QNetworkReply*)) );
    return true;
}


void MainWindow::QnamFinished (QNetworkReply* reply)
{
    if (reply->error())
    {
        showMessage("Cannot download thread");
    }
    else
    {
        showMessage("Parsing html file...");
        parseHtml(reply);
        reply->deleteLater();
        downloadImages();
    }
}


bool MainWindow::parseHtml (QNetworkReply* reply)
{
    QString regExpPar;
    QString strLine;
    QString strHost;
    QString resString;
    int regExpResult;
    QTextStream in(reply);

    imgList.clear();

    switch ( board )
    {
        case INDEX_DVACH_SO:
            regExpPar = "/([a-z]|[0-9])+(/src/)[0-9]+((.png)|(.jpg)|(.gif))";
            strHost = "http://2ch.so";
            break;
        case INDEX_NULLCHAN:
            regExpPar = "/([a-z]|[0-9]|_)+(/src/)[0-9]+((.png)|(.jpg)|(.gif))";   // support 2.0chan
            strHost = "http://www.0chan.ru";
            break;
        case INDEX_FORCHAN:
            regExpPar = "/([a-z]|[0-9])+(/src/)[0-9]+((.png)|(.jpg)|(.gif))";
            strHost = "http://images.4chan.org";
            break;
            default:
            break;
    }

    while ( !reply->atEnd() )
    {
        in >> strLine;
        if ( strLine.indexOf("/src/")!=-1 )
        {
            resString.clear();
            regExpResult = strLine.indexOf(QRegExp(regExpPar));
            if ( regExpResult != -1 )
            {
                while ( strLine[regExpResult] != '.' )
                {
                    resString.push_back(strLine[regExpResult++]);
                }
                for ( int i=0; i<4; ++i ) // for .png, .gif and .jpg
                {
                    resString.push_back(strLine[regExpResult++]);
                }
                resString = strHost + resString;
                imgList += resString;
            }
        }
    }
    imgList.removeDuplicates();
    return true;
}


bool MainWindow::downloadImages()
{
    ui->progressBar->setValue(0);
    if ( imgList.size() == 0 )
    {
        showMessage("Ooops! Bad thread");
        return false;
    }
    showMessage("Downloading images...");
    createDirectory();

    currentImage = 0;

    getNextImage();

    return true;
}


void MainWindow::getNextImage()
{
    if ( currentImage == imgList.size() )
    {
        ui->progressBar->setValue(100);
        ui->lineEdit_thread->setReadOnly(0);
        showMessage("Done");
    }
    else
    {
        QNetworkAccessManager* imgManager = new QNetworkAccessManager(this);
        imgManager->get(  QNetworkRequest(QUrl(imgList[currentImage]))  );
        connect ( imgManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(getImageFinished(QNetworkReply*)) );
    }
}


void MainWindow::getImageFinished(QNetworkReply* reply)
{
    QImage imgFile;
    imgFile.loadFromData(reply->readAll());
    if ( imgFile.isNull() )
    {
        showMessage("Oops. Null image?");
    }
    if ( ! imgFile.save(path + "\\" + QFileInfo( imgList.at(currentImage) ).fileName()) )
    {
        showMessage("Cannot save image. Downloading next...");
    }
    currentImage++;
    ui->progressBar->setValue( (int)((100*currentImage)/imgList.size()) );
    reply->deleteLater();
    getNextImage();
}



